from flask_restful import Resource
from flask_restful.reqparse import RequestParser
from comment.utils import parser
from flask import current_app,request,g
from comment.modules.user import User
from comment.modules.account import Account
from comment.utils.financial_redis import redis_client
from financial.resource.user import constants
from comment.utils.example.SendMessage import send_message
import json
from financial.resource.user.serilazser import InvitedListSerializer
from comment.modules import db
from comment.utils.tokens_pyjwt import generate_tokens,verify_tokens
from comment.utils.decrators import login_required
from financial.resource.account.serializer import AccountInfoSerializer
from .serilazser import UserInfoSerializer

class Login(Resource):
    '''
    登录
    '''
    def post(self):
        rp = RequestParser()
        rp.add_argument('username', required=True)
        rp.add_argument('password', required=True)
        args = rp.parse_args()
        username = args.username #用户名
        password = args.password #密码
        user = User.query.filter(User.username == username).first()
        if user:
            #验证密码
            if user.check_password(password):
                #用户登录成功，生成一个token，以便于后期方便认证
                token = generate_tokens(user.id)
                current_app.logger.info(token)
                current_app.logger.info('测试验证token',verify_tokens(token))
                return {'token':token}
        return {'message':'用户名或密码错误','code':20001}

class LoginOut(Resource):
    '''
    退出登录
    '''
    #登录拦截器
    method_decorators = [login_required]
    #第二种
    # method_decorators = {
    #     'post':login_required,
    #     'get' :login_required
    # }

    def post(self):
        if g.user_id:
            g.user_id = None
        return {'msg':'成功退出登录！'}


class UserAvatar(Resource):
    '''
    用户头像管理
    '''
    method_decorators = [login_required]

    def post(self):
        '''
        上传用户头像图片
        :return:
        '''
        #用户上传图片数据
        img_date = request.files['file']
        id = g.user_id
        user = User.query.filter(User.id == id).first()

        #设置用户头像保存的路径
        img_dir = current_app.config['AVATAR_DIR']

        #设置图像文件的名字
        img_name = str(id) + '_'  +img_date.filename

        #设置完整的文件路径
        file_path = img_dir + '/' + img_name

        #保存文件
        img_date.save(file_path)

        #在数据库中保存用户头像的文件名
        if user:
            user.avatar = img_name
            db.session.commit()
            return {'msg':'上传头像成功','avatar':img_name}



class RegisterUser(Resource):
    '''
    用户的注册
    '''
    def post(self):
        rp = RequestParser()
        rp.add_argument('phone',required=True)
        rp.add_argument('username',required=True)
        rp.add_argument('code',required=True)
        rp.add_argument('password',required=True)
        rp.add_argument('invite_code')

        args = rp.parse_args()#从校验中拿到具体参数
        username = args.username
        code = args.code
        phone = args.phone
        password = args.password
        invite_code = args.invite_code

        #验证用户名是否唯一
        u = User.query.filter(User.username == username).first()
        if u: #用户名存在
            current_app.logger.info('{}:用户名已存在，请更换其他用户名！'.format(username))
            return {'message':'用户名已重复','code':20001}

        # 从redis数据库中得到之前保存的代码
        real_code = redis_client.get('registerCode:{}'.format(phone))
        if not real_code or real_code.decode() != code:  #数据中没有code或者，数据中的code失效了
            current_app.logger.info('验证码错误或失效')
            return {'message': '验证码错误或失效', 'code': 20001}

        #把用户保存到mysql数据库中
        u =User(username=username,pwd=password,phone=phone)

        #验证和关联邀请码
        if invite_code:
            self.check_invite(u ,invite_code)



        try: #需要用到数据库事务处理
            db.session.add(u)
            db.session.flush()  #把数据插入到数据库的缓冲区（得到自增id），并不是插入到数据库中
            account = Account(userId = u.id)
            db.session.add(account)
            db.session.commit()
            return {'msg':'Success!'}
        except Exception as ex:
            current_app.logger.error(ex)
            return {'message': '用户注册时，插入数据库失败！', 'code': '20001'}

    #验证和关联邀请码的
    def check_invite(self,user,invite_code):
        code = invite_code.strip()
        invite_user = user.query.filter(User.inviteId == invite_code).first()
        if invite_user:
            user.invite_user_id = invite_user.id  #如果用户有效，则把这两个用户关联一下
            invite_user.accountInfo.discount += constants.INVITE_MONEY  #邀请账户新用户的人，账户会得到50元代金卷
            invite_user.sumFriends = invite_user.sumFriends + 1 if invite_user.sumFriends else 1  #邀请的人数，累计加1




class IsExistPhone(Resource):
    '''
    判断手机号是否存在
    '''
    def post(self): #post请求的参数往往会封装一个JSON
        phone = request.json.get('phone')
        user = User.query.filter(User.phone == phone).first()
        if user:
            return {'message':'此手机号已被注册，请更换手机号码！','code':'20001'}
        return {'msg':'Success !'}


class SmsCode(Resource):
    '''
    发送短信。验证手机号
    '''
    def get(self):
        phone =request.args['phone'].strip()
        import random
        code = random.randint(1000,9999)
        result = send_message(phone,str(code)) # 返回json字符串
        # re_dict = json.loads(result)   #把json变成字典
        # current_app.logger.info('给手机号为：{}发送短信成功。'.format(phone))
        result = json.loads(result)  # 把json变成字典
        # result 往里面添加一个手机号
        result['phone'] = phone
        # 短信发送成功后，还需要把验证码存放在redis数据库中，以便于下次验证，验证码的时效性为5分中
        reidsclient = redis_client.setex('registerCode:{}'.format(phone), constants.SMS_CODE_EXPIRES,
                                         code)  # 参属1，key: 参数2；时效
        print('reidsclient', reidsclient)
        return result

class AuthorizationCodeResource(Resource):
    """
    提交手机号：开始验证
    """

    def post(self):
        rp = RequestParser()
        rp.add_argument('phone',type=parser.mobile,required=True)
        rp.add_argument('code')
        #rp.add_argument('code',type=parser.mobile(r'^\d{4}$'),required=True)
        args=rp.parse_args()
        phone= args.phone
        code= args.code

        #从redis数据库中得到之前保存的代码
        key = 'shopping:code:{}'.format(phone)
        try:
            real_code = redis_client.get(key) #从redis中返回的是字节数据
        except ConnectionError as e:
            current_app.logger.error(e)
            return {'message:':'redis db connect error.'}, 400

        #开始校验
        if not real_code  or real_code.decode() != code:
            return {'message':'Invalid code.'},400

        return {'phone':phone,'msg':'code success.'}


class Invite(Resource):
    """邀请码奖励管理的资源"""
    # 使用了登录拦截的装饰器
    method_decorators = [login_required]

    def post(self):
        """生成邀请码"""
        u_id = g.user_id
        user = User.query.filter(User.id == u_id).first()
        # 根据用户名，采用UUID算法生成一个唯一邀请码
        import uuid
        invite_code = str(uuid.uuid5(uuid.NAMESPACE_DNS,user.username))
        user.inviteId =invite_code
        db.session.commit()
        return {'message':'Success !!','invite_code':invite_code}

    def get(self):
        """查询被邀请人的列表"""
        u_id = g.user_id

        # 查询被邀请的人
        invite_list = User.query.filter(User.invite_user_id == u_id).all()
        if invite_list:
            data = InvitedListSerializer(invite_list).to_dict()
            return {'msg':'Success !','list':data}
        else:
            return {'msg': 'Success !', 'list': []}




class UserInfo(Resource):
    """用户信息资源类"""
    # 使用了登录拦截的装饰器
    method_decorators = [login_required]

    def get(self):
        """当前登录用户的查询，包括所关联的账户数据"""
        u_id = g.user_id
        user = User.query.filter(User.id == u_id).first()
        user_info_data = UserInfoSerializer(user).to_dict()

        #查询当前用户所对应的账户信息
        acc = Account.query.filter(Account.userId == u_id).first()

        acc_data = {}
        if acc:
            acc_data = AccountInfoSerializer(acc).to_dict()
        return {
            'roles':['admin'] if user.role else ['user'],
            'name':user.username,
            'userInfoDate':user_info_data,
            'accountInfo':acc_data
        }


class PayPassword(Resource):
    """
    设置支付密码
    """

    method_decorators = [login_required]
    # 设置登录验证

    def post(self):
        rp = RequestParser()
        rp.add_argument('pwd', required=True)
        args = rp.parse_args()
        pwd = args.pwd
        id = g.user_id
        user = User.query.filter(User.id == id).first()
        if user:
            user.pay_pwd = pwd
            user.payPwdStatus = 1
            db.session.commit()
            return {'msg': 'success'}
# class UserAvatar(Resource):
#     """用户的头像管理"""
#     # 使用了登录拦截的装饰器
#     method_decorators = [login_required]
#
#     def post(self):
#         """头像图片上传"""
#
#         u_id = g.user_id
#         user = User.query.filter(User.id == u_id).first()
#
#         # 从请求中得到上传的文件数据
#         img_data = request.files['file']
#
#         #指定文件上传路劲
#         import  os
#
#         #  指定文件上传的目录 ,注意：root_path就是当前app所在的目录（绝对路径
#         dir_path = os.path.join(current_app.root_path,'static/avatar')
#
#         #文件保存的完整路劲
#         img_name = str(u_id) + '_' + img_data.filename  # 保证头像图片名称不会重复
#         file_path = os.path.join(dir_path,img_name)
#
#         try:
#             img_data.save(file_path)
#         except Exception as e:
#             current_app.logger.error(e)
#             return {'message':'头像上传失败！'}
#
#         #修改数据库
#         user.avatar = img_name
#         db.session.commit()
#         return {'message':'头像上传成功！','avatar':img_name}


class LoginPwd(Resource):
    '''修改支付密码'''

    def post(self):
        rp = RequestParser()
        rp.add_argument('orgPwd',required=True)
        rp.add_argument('pwd',required=True)
        args = rp.parse_args()
        orgPwd = args.opgpwd
        pwd = args.pwd

        id = g.user_id
        user = User.query.filter(User.id == id).first()
        if user:
            if user.check_password(orgPwd):
                user.pwd = pwd
                db.session.commit()
                return {'msg':'修改成功 ！'}
            else:
                return {'message':'原密码不正确','code':20002}
        return {'message':'server error','code':20001}


class RealNameAuth(Resource):
    """
    实名认证
    """

    method_decorators = [login_required]

    def post(self):
        rp = RequestParser()
        rp.add_argument('realName', required=True)
        rp.add_argument('idNum', required=True)
        args = rp.parse_args()
        realName = args.realName   # 真实姓名
        idNum = args.idNum         # 身份证ID
        id = g.user_id
        user = User.query.filter(User.id == id).first()
        if user.realName:
            return {"code": 20001, 'message': '不可重复验证'}
        else:
            user.realName = realName  # 名字
            user.realNameStatus = 1  # 实名状态
            user.idNum = idNum  # 身份证
            db.session.commit()
            return {'msg': 'success'}



